#include "esp_system.h"
#include <string.h>
#include <stdio.h>
#include "nvs.h"
#include "nvs_flash.h"
#include "esp_log.h"
#include "storage.h"

#define NVC_CONFIG "Config"

static const char *TAG = "storage";

char Target[] = "target";
char nvs_identify[]= "identify";
char nvs_ssid[] = "ssid";
char nvs_pwd[] = "password";

void erase_esp32_keys(void)
{
    nvs_handle_t hand_nvs_conf;
    esp_err_t err = nvs_open("NVC_CONFIG", NVS_READWRITE, &hand_nvs_conf);
    if (ESP_ERR_NVS_NOT_INITIALIZED == err) {
        ESP_LOGE(TAG, "NVS has not been initialized");
        return;
    } else if (ESP_OK != err) {
        ESP_LOGE(TAG, "Failed to open NVS namespaces (0x%x)", err);
        nvs_close(hand_nvs_conf);
        return;
    }

	nvs_erase_key(hand_nvs_conf, "ble_name");

    nvs_commit(hand_nvs_conf);
    nvs_close(hand_nvs_conf);
}

int writeConfigToNvs(char *key, int keyLen, char *inputValue, int valueLen)
{
	nvs_handle_t hand_nvs_conf;
	esp_err_t err = nvs_open("NVC_CONFIG", NVS_READWRITE, &hand_nvs_conf);
	if (ESP_ERR_NVS_NOT_INITIALIZED == err) {
		ESP_LOGE(TAG, "%s: NVS not  initialized."
						"Call nvs_flash_init before starting Wifi/BT", __func__);
		return err;
	} else if (ESP_OK != err) {
		ESP_LOGE(TAG, "%s: failed open NVS namespace (0x%x)", __func__, err);
		nvs_close(hand_nvs_conf);
		return err;
	}

	if (0 == valueLen) {
		ESP_LOGI(TAG, "erase key %s", key);
		nvs_erase_key(hand_nvs_conf, key);
		return err;
	}

	err = nvs_set_blob(hand_nvs_conf, key, inputValue, valueLen);
	if (ESP_OK != err) {
		ESP_LOGE(TAG, "%s: failed set config %s %s(0x%x)", __func__, key,
						inputValue, err);
		nvs_close(hand_nvs_conf);
		return err;
	}
	nvs_commit(hand_nvs_conf);
	nvs_close(hand_nvs_conf);
	return ESP_OK;
}

int readConfigFromNvs(char *key, int keyLen, char *outputValue, int valueMaxLen)
{
	nvs_handle_t hand_nvs_conf;
	esp_err_t err = nvs_open("NVC_CONFIG", NVS_READONLY, &hand_nvs_conf);
	if (ESP_OK != err) {
		ESP_LOGE(TAG, "%s: failed open NVS namespace (0x%x)", __func__, err);
		return err;
	}
	size_t buf_len_short = valueMaxLen - 1;
	size_t required_size = 0;
	err = nvs_get_blob(hand_nvs_conf, key, NULL, &required_size);
	if (ESP_OK != err && ESP_ERR_NVS_NOT_FOUND != err) {
		nvs_close(hand_nvs_conf);
		return err;
	}
	if (required_size <= buf_len_short && 0 != required_size) {
		err = nvs_get_blob(hand_nvs_conf, key, outputValue, &required_size);
	}

	if (ESP_OK != err) {
		ESP_LOGE(TAG, "%s: failed read config %s (0x%x)", __func__, key, err);
		nvs_close(hand_nvs_conf);
		return err;
	}
	ESP_LOGI(TAG, "%s: Success read NVS %s", __func__, key);
	nvs_close(hand_nvs_conf);
	return ESP_OK;
}

uint8_t writeIntegerToNVS(char *key, int keyLen, int32_t inputValue)
{
	nvs_handle_t hand_nvs_conf;
	esp_err_t err = nvs_open("NVC_CONFIG", NVS_READWRITE, &hand_nvs_conf);
	if (ESP_ERR_NVS_NOT_INITIALIZED == err) {
		ESP_LOGE(TAG, "%s: NVS not initialized."
						"Call nvs_flash_init before starting Wifi/BT", __func__);
		return err;
	} else if (ESP_OK != err) {
		ESP_LOGE(TAG, "%s: failed open NVS namespace (0x%x)", __func__, err);
		nvs_close(hand_nvs_conf);
		return err;
	}

	err = nvs_set_i32(hand_nvs_conf, key, inputValue);
	if (ESP_OK != err) {
		ESP_LOGE(TAG, "%s: failed set config %s %ld(0x%x)", __func__, key,
						inputValue, err);
		nvs_close(hand_nvs_conf);
		return err;
	}
	nvs_commit(hand_nvs_conf);
	nvs_close(hand_nvs_conf);
	return ESP_OK;
}

uint8_t readIntegerFromNVS(char *key, int keyLen, int32_t* outputValue)
{
	nvs_handle_t hand_nvs_conf;
	esp_err_t err = nvs_open("NVC_CONFIG", NVS_READONLY, &hand_nvs_conf);
	if (ESP_OK != err) {
		ESP_LOGE(TAG, "%s: failed open NVS namespace (0x%x)", __func__, err);
		return err;
	}
	
	err = nvs_get_i32(hand_nvs_conf, key, outputValue);

	if (ESP_OK != err) {
		ESP_LOGE(TAG, "%s: failed \ read config %s (0x%x)", __func__, key, err);
		nvs_close(hand_nvs_conf);
		return err;
	}
	ESP_LOGI(TAG, "%s: Success read NVS %s", __func__, key);
	nvs_close(hand_nvs_conf);
	return ESP_OK;
}

void setConfigDefault(void)
{
	nvs_handle_t hand_nvs_conf;
    esp_err_t err = nvs_open("NVC_CONFIG", NVS_READWRITE, &hand_nvs_conf);
    if (ESP_ERR_NVS_NOT_INITIALIZED == err) {
        ESP_LOGE(TAG, "NVS not been initialized");
        return;
    } else if (ESP_OK != err) {
        ESP_LOGE(TAG, "Failed open NVS namespaces (0x%x)", err);
        nvs_close(hand_nvs_conf);
        return;
    }

	nvs_erase_key(hand_nvs_conf, Target);

	nvs_commit(hand_nvs_conf);
    nvs_close(hand_nvs_conf);
}

